﻿using Infrastructure.Computer;
using Infrastructure.Image;
using Infrastructure.Web;
using MyData.ApiDto;
using MyData.Dto;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using VideoNet.Common;

namespace VideoNet
{
    public partial class Video : Form
    {
        bool refresh = true;
        int openDoorTime = 5;
        string dicPath = "";
        System.Timers.Timer timer;
        string comPort = "COM1";
        bool needClose = false;
        bool needRestart = false;
        bool m_bInitSDK;
        delegate void SetVisible();
        IntPtr ptr1 = IntPtr.Zero;
        CZCompare compare;
        CHCManage chcmanage = null;
        delegate void delegateRefresh();
        DateTime recordTime = DateTime.Now;
        bool doorStatus = false;
        byte[] OpenCommand = new byte[4] { 0xA0, 0x01, 0x01, 0xA2 };
        byte[] CloseCommand = new byte[4] { 0xA0, 0x01, 0x00, 0xA1 };
        List<CZUserInfo> userList = new List<CZUserInfo>(4);
        List<CZUserInfo> findList = new List<CZUserInfo>();
        MobileLoginOput deviceInfo = null;
        public Video()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
            this.UpdateStyles();
            this.Load += Video_Load;
            this.SizeChanged += Video_SizeChanged;
            this.FormClosing += Video_FormClosing;
        }

        private void Video_FormClosing(object sender, FormClosingEventArgs e)
        {
            needClose = true;
        }

        private void Video_SizeChanged(object sender, EventArgs e)
        {
            float[] scale = (float[])Tag;
            int i = 2;
            if (scale == null)
                return;
            foreach (Control ctrl in this.Controls)
            {
                ctrl.Left = (int)(Size.Width * scale[i++]);
                ctrl.Top = (int)(Size.Height * scale[i++]);
                ctrl.Width = (int)(Size.Width / (float)scale[0] * ((Size)ctrl.Tag).Width);
                ctrl.Height = (int)(Size.Height / (float)scale[1] * ((Size)ctrl.Tag).Height);
                //每次使用的都是最初始的控件大小，保证准确无误。
            }
        }
        string ipaddress = "";
        int port;
        private void Video_Load(object sender, EventArgs e)
        {
            initWindows();
            dicPath = AppDomain.CurrentDomain.BaseDirectory + @"/Images";
            if (!System.IO.Directory.Exists(dicPath))
            {
                System.IO.Directory.CreateDirectory(dicPath);
            }
            try
            {
                port = 8089;
                int.TryParse(ConfigurationManager.AppSettings["Port"].ToString(), out port);
                ipaddress = ComputerHelper.GetIPAddress();
                MobileLoginInput loginModel = new MobileLoginInput() { ImeiNum = ComputerHelper.GetCPUID(), Ip = ipaddress, Port = port };
                string json = WWebClientHelper.GetJson<MobileLoginInput>(loginModel);
                AjaxResult<MobileLoginOput> loginResult = WWebClientHelper.HttpPost<AjaxResult<MobileLoginOput>>(WWebClientHelper.LoginApiString, WWebClientHelper.GetJson<MobileLoginInput>(loginModel));
                deviceInfo = loginResult.data;
                comPort = ConfigurationManager.AppSettings["PortCom"].ToString();
                compare = new CZCompare();
                ptr1 = videoView.Handle;
                WorkStart();
                Task.Factory.StartNew(() =>
                {
                    IPAddress ip = IPAddress.Parse(ipaddress);
                    IPEndPoint ipe = new IPEndPoint(ip, port);//把ip和端口转化为IPEndPoint实例
                    Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个Socket
                    server.Bind(ipe);//绑定2000端口
                    server.Listen(0);//开始监听
                    Socket temp = null;
                    while (!needClose)
                    {
                        temp = server.Accept();//为新建连接创建新的Socket。
                        string recvStr = "";
                        byte[] recvBytes = new byte[1024];
                        int bytes;
                        bytes = temp.Receive(recvBytes, recvBytes.Length, 0);//从客户端接受信息
                        recvStr += Encoding.UTF8.GetString(recvBytes, 0, bytes);
                        if (recvStr == "OK")
                        {
                            needRestart = true;
                        }
                        string sendStr = "";
                        byte[] bs = Encoding.UTF8.GetBytes(sendStr);
                        temp.Send(bs, bs.Length, 0);//返回客户端成功信息
                        temp.Close();
                        GC.Collect();
                    }
                });
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        void WorkStart()
        {
            try
            {
                needClose = false;
                // this.SetNotice();
                m_bInitSDK = CHCNetSDK.NET_DVR_Init();
                if (m_bInitSDK == true)
                {
                    this.timer = new System.Timers.Timer();
                    this.timer.Interval = 500;
                    this.timer.Elapsed += Timer_Elapsed;
                    this.timer.Start();
                    Task.Run(() =>
                    {
                        DoWork();
                    });
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        private void DoWork()
        {

            string cameraIP = ConfigurationManager.AppSettings["CameraIP"].ToString();
            string cameraPort = ConfigurationManager.AppSettings["CameraPort"].ToString();
            string cameraUser = ConfigurationManager.AppSettings["CameraUser"].ToString();
            string cameraPass = ConfigurationManager.AppSettings["CameraPass"].ToString();
            int carport = Convert.ToInt32(cameraPort);
            chcmanage = new CHCManage(cameraIP, carport, cameraUser, cameraPass);
            if (chcmanage.Login())
            {
                chcmanage.Start(ptr1);
            }
            else
            {
                return;
            }
            GetUserInit();
            Thread.Sleep(1000);
            while (!needClose)
            {
                try
                {
                    if (needRestart)
                    {
                        needRestart = false;
                        GetUserInit();
                        MobileLoginInput loginModel = new MobileLoginInput() { ImeiNum = ComputerHelper.GetCPUID(), Ip = ipaddress, Port = port };
                        AjaxResult<MobileLoginOput> loginResult = WWebClientHelper.HttpPost<AjaxResult<MobileLoginOput>>(WWebClientHelper.LoginApiString, WWebClientHelper.GetJson<MobileLoginInput>(loginModel));
                        deviceInfo = loginResult.data;
                        if (chcmanage.Login())
                        {
                            chcmanage.Start(ptr1);
                        }
                    }
                    Image image1 = chcmanage.SaveImage();
                    Bitmap bitmap1 = new Bitmap(image1);
                    Rectangle[] recs = compare.FindFace(bitmap1);
                    if (recs.Length > 0)
                    {
                        recordTime = DateTime.Now;
                        if (!doorStatus)
                        {
                            doorStatus = true;
                            PortHelper.SendCommand(comPort, OpenCommand);
                        }
                        DoFindPerson(bitmap1, recs);
                    }
                    else
                    {
                        if ((DateTime.Now - recordTime).Seconds > openDoorTime && doorStatus)
                        {
                            doorStatus = false;
                            PortHelper.SendCommand(comPort, CloseCommand);
                        }
                    }
                    image1 = null;
                    Thread.Sleep(20);
                    GC.Collect();
                }
                catch (Exception ex)
                {
                }
            }
        }
        void DoFindPerson(Bitmap bitmap, Rectangle[] recs)
        {
            List<float> similars = new List<float>();
            float similar = 0f;
            int hour = DateTime.Now.Hour;
            if (hour >= deviceInfo.DayStart && hour <= deviceInfo.DayEnd)
            {
                similar = deviceInfo.Similar;
            }
            else
            {
                similar = deviceInfo.NightSimilar;
            }
            findList = compare.CheckFaces(bitmap, similar, recs, ref similars);
            if (findList.Count == 0) return;
            bool add = false;
            List<Guid> ids = new List<Guid>();
            foreach (var item in findList)
            {
                if (userList.Select(c => c.Id).Contains(item.Id)||ids.Contains(item.Id))
                    continue;
                if (userList.Count == 4)
                    userList.RemoveAt(3);
                item.FindTime = DateTime.Now;
                userList.Insert(0, item);
                add = true;
                ids.Add(item.Id);
            }
            if (add)
            {
                this.refresh = true;
                this.Timer_Elapsed(null, null);
                string base64 = ImageHelper.GetBase64FromImage(bitmap);
                BatchAccessRecord batchModel = new BatchAccessRecord();
                List<AccessRecordApiDto> dtos = new List<AccessRecordApiDto>();
                for (var i = 0; i < findList.Count; i++)
                {
                    dtos.Add(new AccessRecordApiDto() { Similar = similars[i], UserId = findList[i].Id });
                }
                batchModel.Base64 = base64;
                batchModel.AccessRecords = dtos;
                batchModel.MobileId = deviceInfo.Id;
                batchModel.TurnOver = deviceInfo.TurnOver;
                AjaxResult result = WWebClientHelper.HttpPost<AjaxResult>(WWebClientHelper.SaveBatchAccessRecordApiString, WWebClientHelper.GetJson<BatchAccessRecord>(batchModel));
                delegateRefresh del = new delegateRefresh(RefreshForm);
                this.Invoke(del, null);
            }
        }
        private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (refresh)
            {
                refresh = false;
                delegateRefresh del = new delegateRefresh(RefreshForm);
                this.Invoke(del, null);
            }
            List<Guid> list = new List<Guid>();
            foreach (var item in userList)
            {
                if ((DateTime.Now - item.FindTime).Seconds > openDoorTime)
                {
                    list.Add(item.Id);
                    //SendCommand(CloseCommand);
                }
            }
            userList.RemoveAll(c => list.Contains(c.Id));
            picControls1.RefreshForm(userList, dicPath);
            if (DateTime.Now.Minute % 5 == 0 && DateTime.Now.Second == 0)
            {
                MobileLoginInput loginModel = new MobileLoginInput() { ImeiNum = ComputerHelper.GetCPUID(), Ip = ipaddress, Port = port };
                AjaxResult<MobileLoginOput> loginResult = WWebClientHelper.HttpPost<AjaxResult<MobileLoginOput>>(WWebClientHelper.LoginApiString, WWebClientHelper.GetJson<MobileLoginInput>(loginModel));
            }
        }
        void RefreshForm()
        {
            picControls1.RefreshForm(userList, dicPath);
            this.recordControl1.SetRefresh(deviceInfo.Id);
        }
        /// <summary>
        /// 适应大小
        /// </summary>
        private void initWindows()
        {
            int count = this.Controls.Count * 2 + 2;
            float[] factor = new float[count];
            int i = 0;
            factor[i++] = Size.Width;
            factor[i++] = Size.Height;
            foreach (Control ctrl in this.Controls)
            {
                factor[i++] = ctrl.Location.X / (float)Size.Width;
                factor[i++] = ctrl.Location.Y / (float)Size.Height;
                ctrl.Tag = ctrl.Size;
            }
            Tag = factor;
        }
        void GetUserInit()
        {
            LoadingControl pLoading = LoadingControl.getLoading();
            pLoading.SetExecuteMethod(method);
            pLoading.ShowDialog();
        }
        WebClient client;
        private void method()
        {
            LoadingControl pLoading = LoadingControl.getLoading();
            try
            {
                SynsInputP synsIn = new SynsInputP() { MobileId = deviceInfo.Id, PageSize = 10, PageIndex = 1 };
                AjaxResult<SynsOput> syns = WWebClientHelper.HttpPost<AjaxResult<SynsOput>>(WWebClientHelper.SynsApiString, WWebClientHelper.GetJson<SynsInputP>(synsIn));
                if (syns.data.DeleteUserIds != null && syns.data.DeleteUserIds.Count > 0)
                {
                    compare.Delete(syns.data.DeleteUserIds, dicPath);
                }
                if (syns.data.DeleteVisitors != null && syns.data.DeleteVisitors.Count > 0)
                {
                    compare.Delete(syns.data.DeleteVisitors, dicPath);
                }
                int total = syns.data.TotolPage;
                if (syns.data.UserInfoSynsOputs != null)
                {
                    foreach (var user in syns.data.UserInfoSynsOputs)
                    {
                        client = new WebClient();
                        if (System.IO.File.Exists(dicPath + "/" + user.UserId + ".jpg"))
                        {
                            System.IO.File.Delete(dicPath + "/" + user.UserId + ".jpg");
                        }
                        client.DownloadFile(WWebClientHelper.BaseApi + user.HeadUrl, dicPath + "/" + user.UserId + ".jpg");
                        compare.Register(new CZUserInfo() { Id = user.UserId, Name = user.NickName, ImagePath = "/" + user.UserId + ".jpg", FindTime = DateTime.Now }, dicPath);
                        pLoading.SetCaptionAndDescription("", "", "执行进度" + 0 + "/" + total);

                    }
                }
                for (var i = 1; i < syns.data.TotolPage; i++)
                {
                    synsIn = new SynsInputP() { MobileId = deviceInfo.Id, PageSize = 10, PageIndex = i + 1 };
                    syns = WWebClientHelper.HttpPost<AjaxResult<SynsOput>>(WWebClientHelper.SynsApiString, WWebClientHelper.GetJson<SynsInputP>(synsIn));
                    foreach (var user in syns.data.UserInfoSynsOputs)
                    {
                        client = new WebClient();
                        if (System.IO.File.Exists(dicPath + "/" + user.UserId + ".jpg"))
                        {
                            System.IO.File.Delete(dicPath + "/" + user.UserId + ".jpg");
                        }
                        client.DownloadFile(WWebClientHelper.BaseApi + user.HeadUrl, dicPath + "/" + user.UserId + ".jpg");
                        compare.Register(new CZUserInfo() { Id = user.UserId, Name = user.NickName, ImagePath = "/" + user.UserId + ".jpg", FindTime = DateTime.Now }, dicPath);
                        pLoading.SetCaptionAndDescription("", "", "执行进度" + i + "/" + total);
                    }
                }
                if (syns.data.VisitorSynsOputs != null)
                {

                    foreach (var visitor in syns.data.VisitorSynsOputs)
                    {
                        client = new WebClient();
                        if (System.IO.File.Exists(dicPath + "/" + visitor.VisitorId + ".jpg"))
                        {
                            System.IO.File.Delete(dicPath + "/" + visitor.VisitorId + ".jpg");
                        }
                        client.DownloadFile(WWebClientHelper.BaseApi + visitor.HeadUrl, dicPath + "/" + visitor.VisitorId + ".jpg");
                        compare.Register(new CZUserInfo() { Id = visitor.VisitorId, Name = visitor.Name, ImagePath = "/" + visitor.VisitorId + ".jpg", FindTime = DateTime.Now, UserType = 1 }, dicPath);
                        pLoading.SetCaptionAndDescription("", "", "执行进度" + 0 + "/" + total);

                    }
                }
                SynsInput synsOK = new SynsInput() { MobileId = deviceInfo.Id };
                AjaxResult deleteResult = WWebClientHelper.HttpPost<AjaxResult<SynsOput>>(WWebClientHelper.SynsSuccessApiString, WWebClientHelper.GetJson<SynsInput>(synsOK));

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            compare.Reload();
            LoadingControl.getLoading().CloseLoadingForm();
        }
    }
}
